﻿using System;
using System.Collections;
using System.Collections.Generic;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.ExtensibleStorage;
using YArchitech.Revit;
using YJKArchUtils.Utils;
using YJKRevitBase.TopologySuite;
using YJKRevitKernel.RevitTopologySuite;
using YJKRevitKernel.XYZUtility;
using YJKLoopSearch;

namespace YJKRevitDimensionText.OneKeyPlanDim.Utility
{
	public class CommonInterface
	{
		public static Element GetElement(ElementId eleId, List<Document> lstDoc)
		{
			foreach (Autodesk.Revit.DB.Document document in lstDoc)
			{
				Element element = document.GetElement(eleId);
				if (element != null)
				{
					return element;
				}
			}
			return null;
		}

		public static bool GetCurveProject(Curve cv, Curve cvProj, out Curve cvResult)
		{
			cvResult = null;
			try
			{
				Curve curve = cvProj.Clone();
				if (curve.IsBound)
				{
					curve.MakeUnbound();
				}
				XYZ xyzpoint = curve.Project(cv.GetEndPoint(0)).XYZPoint;
				XYZ xyzpoint2 = curve.Project(cv.GetEndPoint(1)).XYZPoint;
				if (cvProj is Line)
				{
					cvResult = Line.CreateBound(xyzpoint, xyzpoint2);
					return true;
				}
				if (cvProj is Arc)
				{
					XYZ xyzpoint3 = cvProj.Project((xyzpoint + xyzpoint2) / 2.0).XYZPoint;
					cvResult = Arc.Create(xyzpoint, xyzpoint2, xyzpoint3);
					return true;
				}
			}
			catch (Exception)
			{
				return false;
			}
			return false;
		}

		public static XYZ PtInPlanarFaceInDir(XYZ ptOri, PlanarFace planarFace, XYZ vec)
		{
			XYZ zero = XYZ.Zero;
			if (planarFace == null || ptOri == null || vec == null)
			{
				return zero;
			}
			Line line = Line.CreateUnbound(ptOri, vec);
			IntersectionResultArray intersectionResultArray = null;
			planarFace.Intersect(line, out intersectionResultArray);
			if (intersectionResultArray != null && !intersectionResultArray.IsEmpty)
			{
				IEnumerator enumerator = intersectionResultArray.GetEnumerator();
				{
					if (enumerator.MoveNext())
					{
						return ((IntersectionResult)enumerator.Current).XYZPoint;
					}
				}
				return zero;
			}
			return zero;
		}

		public static bool IsExistOcclusion(CurveLoop curveLoop, List<CurveLoop> lstCvLoop)
		{
			try
			{
				if (lstCvLoop.Count == 0)
				{
					return false;
				}
				RevitPolygonDataBean revitPolygonDataBean = new RevitPolygonDataBean(curveLoop, null, 3);
				foreach (CurveLoop curveLoop2 in lstCvLoop)
				{
					RevitPolygonDataBean revitPolygonDataBean2 = new RevitPolygonDataBean(curveLoop2, null, 3);
					TopologyRelateKindEnum topologyRelateKindEnum = 0;
					new RevitPolygonRelateOperater().TryGetPolygonRelate(revitPolygonDataBean, revitPolygonDataBean2, out topologyRelateKindEnum);
                    if ((int)topologyRelateKindEnum != 1 && (int)topologyRelateKindEnum != 3)
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		public static bool IsExistOcclusion(List<CurveLoop> lstCvLoop, List<CurveLoop> lstCvLoopTarget)
		{
			using (List<CurveLoop>.Enumerator enumerator = lstCvLoop.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					if (CommonInterface.IsExistOcclusion(enumerator.Current, lstCvLoopTarget))
					{
						return true;
					}
				}
			}
			return false;
		}

		public static void CreateModelCurve(Autodesk.Revit.DB.Document doc, List<CurveLoop> lstCvLoop)
		{
			Transaction transaction = new Transaction(doc, "CreateModelCurve");
			try
			{
				transaction.Start();
				Plane plane = RevitVersionFuncs.CreatePlanByNormalAndOrigin(XYZ.BasisZ, XYZ.Zero);
				SketchPlane sketchPlane = SketchPlane.Create(doc, plane);
				CurveArray curveArray = new CurveArray();
				foreach (CurveLoop curveLoop in lstCvLoop)
				{
					foreach (Curve curve in curveLoop)
					{
						curveArray.Append(curve);
					}
				}
				doc.Create.NewModelCurveArray(curveArray, sketchPlane);
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
			}
		}

		public static void CreateModelCurve(Autodesk.Revit.DB.Document doc, List<Curve> lstCv)
		{
			Transaction transaction = new Transaction(doc, "CreateModelCurve");
			try
			{
				transaction.Start();
				Plane plane = RevitVersionFuncs.CreatePlanByNormalAndOrigin(XYZ.BasisZ, lstCv[0].GetEndPoint(0));
				SketchPlane sketchPlane = SketchPlane.Create(doc, plane);
				CurveArray curveArray = new CurveArray();
				foreach (Curve curve in lstCv)
				{
					curveArray.Append(curve);
				}
				doc.Create.NewModelCurveArray(curveArray, sketchPlane);
				transaction.Commit();
			}
			catch
			{
			}
		}

		public static void CreateModelCurve(Autodesk.Revit.DB.Document doc, Curve cv)
		{
			Transaction transaction = new Transaction(doc, "CreateModelCurve");
			try
			{
				transaction.Start();
				Plane plane = RevitVersionFuncs.CreatePlanByNormalAndOrigin(XYZ.BasisZ, cv.GetEndPoint(0));
				SketchPlane sketchPlane = SketchPlane.Create(doc, plane);
				CurveArray curveArray = new CurveArray();
				curveArray.Append(cv);
				doc.Create.NewModelCurveArray(curveArray, sketchPlane);
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
			}
		}

		public static List<CurveLoop> MoveLstCurve(List<CurveLoop> lstCvLoop, XYZ ptStart, XYZ ptEnd)
		{
			List<CurveLoop> list = new List<CurveLoop>();
			if (ptStart.IsAlmostEqualTo(ptEnd))
			{
				list.AddRange(lstCvLoop);
				return list;
			}
			foreach (CurveLoop curveLoop in lstCvLoop)
			{
				CurveLoop item = CommonInterface.MoveCurve(curveLoop, ptStart, ptEnd);
				list.Add(item);
			}
			return list;
		}

		public static CurveLoop RotateCurve(CurveLoop curveLoop, XYZ ptBase, double dRotAngle)
		{
			Transform transform = RevitVersionFuncs.CreateRotationAtPoint(XYZ.BasisZ, dRotAngle, ptBase);
			return CurveLoop.CreateViaTransform(curveLoop, transform);
		}

		public static CurveLoop MoveCurve(CurveLoop curveLoop, XYZ ptStart, XYZ ptEnd)
		{
			Transform transform = Transform.CreateTranslation(ptEnd - ptStart);
			new List<Curve>();
			return CurveLoop.CreateViaTransform(curveLoop, transform);
		}

		public static Element MoveElement(Element ele, XYZ ptStart, XYZ ptEnd, Autodesk.Revit.DB.Document doc)
		{
			if (ptStart.IsAlmostEqualTo(ptEnd))
			{
				return ele;
			}
			try
			{
				Transaction transaction = new Transaction(doc, "MoveElement");
				transaction.Start();
				XYZ xyz = ptEnd - ptStart;
				ElementTransformUtils.MoveElement(doc, ele.Id, xyz);
				transaction.Commit();
			}
			catch
			{
			}
			return ele;
		}

		public static Element RotateElement(Element ele, XYZ basePnt, XYZ vector, double dDegree)
		{
			if (Geometry.IsEqual(dDegree, 0.0))
			{
				return ele;
			}
			try
			{
				Transaction transaction = new Transaction(ele.Document, "RolateElement");
				transaction.Start();
				Document document = ele.Document;
				Line line = RevitDocumentExtension.CreatYJKLine(document, basePnt, vector, false);
				ElementTransformUtils.RotateElement(document, ele.Id, line, dDegree);
				transaction.Commit();
			}
			catch
			{
			}
			return ele;
		}

		public static XYZ GetNumCorrespondingOffsetPoint(int nNum, double dOffsetDistance, XYZ ptOrigin, XYZ vtOffset)
		{
			if (nNum == 0)
			{
				return ptOrigin;
			}
			XYZ result;
			if (nNum % 2 == 0)
			{
				result = ptOrigin - vtOffset * (double)(nNum / 2) * dOffsetDistance;
			}
			else
			{
				result = ptOrigin + vtOffset * (double)((nNum + 1) / 2) * dOffsetDistance;
			}
			return result;
		}

		public static double CoreUpThickness(Element roof)
		{
			double result = 0.0;
			if (roof is Floor)
			{
				result = CommonInterface.GetThicknessWithWallType((roof as Floor).FloorType);
			}
			else if (roof is RoofBase)
			{
				result = CommonInterface.GetThicknessWithWallType((roof as RoofBase).RoofType);
			}
			return result;
		}

		private static double GetThicknessWithWallType(HostObjAttributes type)
		{
			double num = 0.0;
			CompoundStructure compoundStructure = type.GetCompoundStructure();
			int firstCoreLayerIndex = compoundStructure.GetFirstCoreLayerIndex();
			IList<CompoundStructureLayer> layers = compoundStructure.GetLayers();
			int count = layers.Count;
			new List<int>();
			for (int i = 0; i < count; i++)
			{
				CompoundStructureLayer compoundStructureLayer = layers[i];
				if (i < firstCoreLayerIndex)
				{
					num += compoundStructureLayer.Width;
				}
			}
			return num;
		}

		public static XYZ GetNextPositionByOffset(int nNum, double dOffsetDistance, XYZ ptOrigin, XYZ vtOffset)
		{
			if (nNum == 0)
			{
				return ptOrigin;
			}
			return ptOrigin + vtOffset.Normalize() * (double)nNum * dOffsetDistance;
		}

		public static XYZ GetNumCorrespondingOffsetPoint(int nSum, int nNum, double dOffsetDistance, XYZ ptOrigin)
		{
			if (nNum > nSum)
			{
				return ptOrigin;
			}
			if (nNum == 0)
			{
				return ptOrigin;
			}
			int num = nSum / 2;
			if (nSum % 2 != 0)
			{
				return ptOrigin;
			}
			XYZ basisY = XYZ.BasisY;
			double num2 = Math.PI*2 / (double)num;
			double num3 = dOffsetDistance;
			if (nNum > num)
			{
				num3 = dOffsetDistance * 2.0;
			}
			XYZ xyz = basisY * num3;
			XYZ xyz2 = ptOrigin - new XYZ(ptOrigin.X, ptOrigin.Y, ptOrigin.Z + 10.0);
			XYZ xyz3 = XYZUtilityMethod.RotateTo(xyz, num2, xyz2);
			return new XYZ(xyz3.X + ptOrigin.X, xyz3.Y + ptOrigin.Y, ptOrigin.Z);
		}

		public static bool IsHasGuid(Element elem, string strGuid)
		{
			if (elem == null)
			{
				return false;
			}
			Schema schema = Schema.Lookup(new Guid(strGuid));
			if (schema == null)
			{
				return false;
			}
			Entity entity = elem.GetEntity(schema);
			return entity.IsValid() && entity.Schema != null;
		}

		public static DetailCurve CreateDetailCurve(Autodesk.Revit.DB.Document doc, XYZ ptStart, XYZ ptEnd)
		{
			Transaction transaction = new Transaction(doc, "CreateDetailCurve");
			DetailCurve result;
			try
			{
				transaction.Start();
				Line line = Line.CreateBound(ptStart, ptEnd);
				DetailCurve detailCurve = doc.Create.NewDetailCurve(doc.ActiveView, line);
				transaction.Commit();
				result = detailCurve;
			}
			catch (Exception)
			{
				result = null;
			}
			return result;
		}

		public static DetailCurve CreateDetailCurve(Autodesk.Revit.DB.Document doc, Line line)
		{
			if (!line.IsBound)
			{
				return null;
			}
			Transaction transaction = new Transaction(doc, "CreateDetailCurve");
			DetailCurve result;
			try
			{
				transaction.Start();
				DetailCurve detailCurve = doc.Create.NewDetailCurve(doc.ActiveView, line);
				transaction.Commit();
				result = detailCurve;
			}
			catch (Exception)
			{
				result = null;
			}
			return result;
		}

		public static DetailCurve GetDetailCurveWithPoint(Autodesk.Revit.DB.Document doc, XYZ startPoint, XYZ dir)
		{
			XYZ ptEnd = startPoint + dir * Common.MMToFeet(10.0);
			return CommonInterface.CreateDetailCurve(doc, startPoint, ptEnd);
		}

		public static Line NextDodgeLine(Line curLine, XYZ dir, double dLength)
		{
			Transform transform = Transform.CreateTranslation(dir.Normalize() * dLength);
			return curLine.CreateTransformed(transform) as Line;
		}

		public static Curve GetXYPlaneCurve(Curve curve)
		{
			try
			{
				if (curve.GetType() == typeof(Line))
				{
					Line line = curve as Line;
					if (!line.IsBound)
					{
						return Line.CreateUnbound(new XYZ(line.Origin.X, line.Origin.Y, 0.0), line.Direction);
					}
					XYZ endPoint = curve.GetEndPoint(0);
					XYZ endPoint2 = curve.GetEndPoint(1);
					XYZ xyz = new XYZ(endPoint.X * 100.0, endPoint.Y * 100.0, 0.0);
					XYZ xyz2 = new XYZ(endPoint2.X * 100.0, endPoint2.Y * 100.0, 0.0);
					Curve curve2 = Line.CreateBound(xyz, xyz2);
					Transform transform = Transform.CreateTranslation(new XYZ(0.0, 0.0, 0.0));
					transform = transform.ScaleBasis(0.01);
					return curve2.CreateTransformed(transform);
				}
				else
				{
					if (curve.GetType() == typeof(Arc))
					{
						Arc arc = curve as Arc;
						double num = arc.ComputeRawParameter(0.0);
						double num2 = arc.ComputeRawParameter(1.0);
						return Arc.Create(new XYZ(arc.Center.X, arc.Center.Y, 0.0), arc.Radius, num, num2, arc.XDirection, arc.YDirection);
					}
					if (curve.GetType() == typeof(HermiteSpline))
					{
						XYZ endPoint3 = curve.GetEndPoint(0);
						XYZ endPoint4 = curve.GetEndPoint(1);
						XYZ xyz3 = new XYZ(endPoint3.X * 100.0, endPoint3.Y * 100.0, 0.0);
						XYZ xyz4 = new XYZ(endPoint4.X * 100.0, endPoint4.Y * 100.0, 0.0);
						Curve curve3 = Line.CreateBound(xyz3, xyz4);
						Transform transform2 = Transform.CreateTranslation(new XYZ(0.0, 0.0, 0.0));
						transform2 = transform2.ScaleBasis(0.01);
						return curve3.CreateTransformed(transform2);
					}
				}
			}
			catch
			{
			}
			return curve;
		}

		public static List<XYZ> GetXYPlanePt(List<XYZ> lstCv)
		{
			List<XYZ> list = new List<XYZ>();
			foreach (XYZ xyz in lstCv)
			{
				list.Add(new XYZ(xyz.X, xyz.Y, 0.0));
			}
			return list;
		}

		public static List<Curve> GetXYPlaneCurve(List<Curve> lstCv)
		{
			List<Curve> list = new List<Curve>();
			foreach (Curve curve in lstCv)
			{
				list.Add(CommonInterface.GetXYPlaneCurve(curve));
			}
			return list;
		}

		public static CurveLoop GetXYPlaneCurve(CurveLoop curveLoop)
		{
			CurveLoop curveLoop2 = new CurveLoop();
			foreach (Curve curve in curveLoop)
			{
				Curve xyplaneCurve = CommonInterface.GetXYPlaneCurve(curve);
				if (!(xyplaneCurve == null))
				{
					curveLoop2.Append(xyplaneCurve);
				}
			}
			return curveLoop2;
		}

		public static List<CurveLoop> CreateLoopsByCurves(Autodesk.Revit.DB.Document doc, List<Curve> lstCvs)
		{
			List<CurveLoop> lstLoops = new List<CurveLoop>();
			try
			{
				List<Pole2D> lstPole = new List<Pole2D>();
				lstCvs.ForEach(delegate(Curve e)
				{
					Pole2D item = Pole2D.TransformWallToStructure2DPole(e, ElementId.InvalidElementId, 0.0, 0.0);
					lstPole.Add(item);
				});
				new StructureLoopSearcher(doc).GetCellsEdgeLoops(lstPole, false).ForEach(delegate(List<Curve> cvs)
				{
					CurveLoop item = CurveLoop.Create(cvs);
					lstLoops.Add(item);
				});
			}
			catch
			{
			}
			return lstLoops;
		}
	}
}
